function Observer(data) {
    // data = {msg: 'hello'}保存data
    this.data = data;
    // 开始对data的监视
    this.walk(data);
}

Observer.prototype = {
    walk: function(data) {
        // this是Observer实例对象
        var me = this;
        // 遍历data的属性
        Object.keys(data).forEach(function(key) {
            // 传入属性值和属性值 对指定属性进行劫持
            me.convert(key, data[key]);
        });
    },
    convert: function(key, val) {
        // 响应式数据绑定：数据和界面同步变化
        this.defineReactive(this.data, key, val);
    },
    // 实现响应式数据绑定
    defineReactive: function(data, key, val) {
        // 初始化的时候创建Dep实例（给data的属性进行数据劫持时创建）
        // 与data中的属性一一对应，data属性的属性的属性也算
        // dependency dep关联多个watcher watcher对应表达式 表达式使用了属性key
        var dep = new Dep();
        // 通过间接递归调用，实现对data中所有层次属性的数据劫持
        var childObj = observe(val);
        // 给data重新定义key的属性 添加getter和setter
        Object.defineProperty(data, key, {
            enumerable: true, // 可枚举
            configurable: false, // 不能再define
            // 读取数据的时候进入get
            get: function() {
                // 建立Dep和Watcher的关系
                if (Dep.target) {
                    // 建立关系
                    dep.depend();
                }
                // 返回值
                return val;
            },
            // 修改数据的时候进入set 监视key属性的变化 更新界面
            set: function(newVal) {
                if (newVal === val) {
                    return;
                }
                val = newVal;
                // 新的值是object的话，进行监听，
                // 间接递归调用，对数据内部的数据进行数据绑定，所有层次的数据
                childObj = observe(newVal);
                // 通知所有订阅者Watcher
                dep.notify();
            }
        });
    }
};

function observe(value, vm) {
    // 递归结束条件 观察的是对象的属性 不是对象就不存在观察
    if (!value || typeof value !== 'object') {
        return;
    }
    // 创建对应的Observer对象
    return new Observer(value);
};


var uid = 0;

function Dep() {
    // 标识
    this.id = uid++;
    // 存放多个订阅者：存放的是n个相关的Watcher实例
    this.subs = [];
}

Dep.prototype = {
    // 添加Watcher到Dep中
    addSub: function(sub) {
        this.subs.push(sub);
    },
    // 建立Dep和Watcher的关系
    depend: function() {
        Dep.target.addDep(this);
    },

    removeSub: function(sub) {
        var index = this.subs.indexOf(sub);
        if (index != -1) {
            this.subs.splice(index, 1);
        }
    },
    
    notify: function() {
        // 遍历subs里面存放的是Watcher
        this.subs.forEach(function(sub) {
            // 调用每个Watcher的update方法
            sub.update();
        });
    }
};

Dep.target = null;